Intermediate Level Interview Question
-
Explain the difference between
__str__()
and__repr__()
methods in Python classes.- Answer:
__str__()
is used to compute the "informal" or nicely printable string representation of an object. It's meant to be readable.__repr__()
computes the "official" string representation that is intended for debugging and re-creation of the object witheval()
.
class MyClass:
def __init__(self, x, y):
self.x = x
self.y = y
def __str__(self):
return f'MyClass({self.x}, {self.y})'
def __repr__(self):
return f'MyClass({self.x}, {self.y})'
obj = MyClass(10, 20)
print(str(obj)) # Output: MyClass(10, 20)
print(repr(obj)) # Output: MyClass(10, 20)
- Answer:
-
What are decorators in Python? How do you implement them?
- Answer: Decorators are functions that modify the functionality of another function or class. They are used to wrap another function or class, adding some additional functionality before or after the original function or class.
def my_decorator(func):
def wrapper():
print("Something is happening before the function is called.")
func()
print("Something is happening after the function is called.")
return wrapper
@my_decorator
def say_hello():
print("Hello!")
say_hello()
# Output:
# Something is happening before the function is called.
# Hello!
# Something is happening after the function is called.
- Answer: Decorators are functions that modify the functionality of another function or class. They are used to wrap another function or class, adding some additional functionality before or after the original function or class.
-
Explain the concept of
self
in Python.- Answer:
self
refers to the instance of a class. It allows you to access the instance's attributes and methods from within the class definition.class MyClass:
def __init__(self, x):
self.x = x
def print_value(self):
print(self.x)
obj = MyClass(10)
obj.print_value() # Output: 10
- Answer:
-
What are
classmethod
andstaticmethod
in Python?- Answer:
classmethod
: It is a method that is bound to the class rather than the instance of the class. It takescls
as the first parameter, which refers to the class itself.staticmethod
: It is a method that is not bound to either the class or the instance. It behaves like a regular function but is defined inside a class for organizational purposes.
class MyClass:
class_attr = 10
@classmethod
def class_method(cls):
print(f'Class attribute: {cls.class_attr}')
@staticmethod
def static_method():
print('This is a static method')
MyClass.class_method() # Output: Class attribute: 10
MyClass.static_method() # Output: This is a static method
- Answer:
-
What is method resolution order (MRO) in Python?
- Answer: Method Resolution Order (MRO) determines the order in which methods are inherited in the presence of multiple inheritance. It is computed using the C3 linearization algorithm.
class A:
def process(self):
print('A process()')
class B(A):
def process(self):
print('B process()')
class C(A):
def process(self):
print('C process()')
class D(B, C):
pass
obj = D()
obj.process()
# Output: B process()
- Answer: Method Resolution Order (MRO) determines the order in which methods are inherited in the presence of multiple inheritance. It is computed using the C3 linearization algorithm.
-
Explain the use of
super()
in Python with an example.- Answer:
super()
is used to call methods of a superclass (parent class) in a derived class (child class).class A:
def greet(self):
print('Hello from class A')
class B(A):
def greet(self):
super().greet() # Call greet() method of class A
print('Hello from class B')
obj = B()
obj.greet()
# Output:
# Hello from class A
# Hello from class B
- Answer:
-
How do you handle exceptions using
try
,except
,else
, andfinally
blocks in Python?- Answer:
try
: It is used to wrap the code that might throw an exception.except
: It is used to handle the exception iftry
block raises one.else
: It is executed if thetry
block executes without raising an exception.finally
: It is always executed whether an exception occurred or not.
try:
result = 10 / 0
except ZeroDivisionError:
print("Cannot divide by zero")
else:
print("Division successful")
finally:
print("This block is always executed")
- Answer:
-
How do you use Python's
logging
module for logging messages?- Answer: The
logging
module provides a flexible framework for emitting log messages from Python programs.import logging
logging.basicConfig(level=logging.DEBUG, format='%(asctime)s - %(levelname)s - %(message)s')
logging.debug('This is a debug message')
logging.info('This is an info message')
logging.warning('This is a warning message')
logging.error('This is an error message')
logging.critical('This is a critical message')
- Answer: The
-
Explain the difference between
deepcopy()
andcopy()
functions in Python'scopy
module.- Answer:
copy()
: It creates a shallow copy of the object. The copied object itself is new, but the elements within it are references to the original elements.deepcopy()
: It creates a deep copy of the object. The copied object and its elements are completely new, recursively copied from the original.
import copy
original = [[1, 2, 3], [4, 5, 6]]
shallow_copy = copy.copy(original)
deep_copy = copy.deepcopy(original)
original[0][0] = 99
print(original) # Output: [[99, 2, 3], [4, 5, 6]]
print(shallow_copy) # Output: [[99, 2, 3], [4, 5, 6]]
print(deep_copy) # Output: [[1, 2, 3], [4, 5, 6]]
- Answer:
-
How do you use list comprehensions in Python? Provide an example.
- Answer: List comprehensions provide a concise way to create lists.
numbers = [1, 2, 3, 4, 5]
squares = [x * x for x in numbers if x % 2 == 0]
print(squares) # Output: [4, 16]
- Answer: List comprehensions provide a concise way to create lists.
-
What are
lambda
functions in Python? Provide an example.- Answer:
lambda
functions are anonymous functions defined with thelambda
keyword.square = lambda x: x * x
print(square(5)) # Output: 25
- Answer:
-
How do you sort a dictionary by value in Python?
- Answer: You can use the
sorted()
function with a custom key to sort a dictionary by its values.my_dict = {'a': 3, 'b': 1, 'c': 2}
sorted_dict = dict(sorted(my_dict.items(), key=lambda item: item[1]))
print(sorted_dict) # Output: {'b': 1, 'c': 2, 'a': 3}
- Answer: You can use the
-
What is the purpose of the
__init__()
method in Python classes?- Answer: The
__init__()
method (initializer or constructor) is automatically called when a new instance of a class is created. It initializes the object's attributes.class MyClass:
def __init__(self, x):
self.x = x
obj = MyClass(10)
print(obj.x) # Output: 10
- Answer: The
-
How do you handle file operations (open, read, write, close) in Python?
- Answer: You can use the
open()
function to open a file,read()
orwrite()
methods to read from or write to it, andclose()
method to close it.# Reading from a file
with open('file.txt', 'r') as file:
content = file.read()
print(content)
# Writing to a file
with open('file.txt', 'w') as file:
file.write('Hello, World!')
- Answer: You can use the
-
How do you use regular expressions (
re
module) in Python?- Answer: The
re
module provides support for regular expressions in Python.import re
text = "Hello, my email is example@email.com"
pattern = r'\b[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Z|a-z]{2,}\b'
emails = re.findall(pattern, text)
print(emails) # Output: ['example@email.com']
- Answer: The
-
Explain the difference between
asyncio
andthreading
in Python.- Answer:
asyncio
: It is a library for writing concurrent code using theasync
andawait
keywords. It is single-threaded and cooperatively multitasks.threading
: It is a standard module for creating and working with threads. Threads are OS-level lightweight processes, and Python threads are real system threads.
import asyncio
import threading
import time
async def async_task():
print('Async task starting')
await asyncio.sleep(2)
print('Async task done')
def sync_task():
print('Sync task starting')
time.sleep(2)
print('Sync task done')
async def main():
asyncio.create_task(async_task())
await asyncio.sleep(1)
threading.Thread(target=sync_task).start()
asyncio.run(main())
- Answer:
-
Explain the concept of
yield
in Python and provide an example of its usage.- Answer:
yield
is used inside a function to turn it into a generator. It returns an iterator that generates values lazily as they are requested.def my_generator():
yield 1
yield 2
yield 3
gen = my_generator()
print(next(gen)) # Output: 1
print(next(gen)) # Output: 2
print(next(gen)) # Output: 3
- Answer:
-
How do you serialize and deserialize Python objects?
- Answer: Serialization is the process of converting a Python object into a byte stream, and deserialization is the reverse process.
import pickle
# Serialization
data = {'name': 'Alice', 'age': 30}
serialized = pickle.dumps(data)
# Deserialization
deserialized = pickle.loads(serialized)
print(deserialized) # Output: {'name': 'Alice', 'age': 30}
- Answer: Serialization is the process of converting a Python object into a byte stream, and deserialization is the reverse process.
-
What are context managers in Python and how do you use them?
- Answer: Context managers are objects that enable proper resource management. They are used with the
with
statement.class MyContextManager:
def __enter__(self):
print('Entering context')
return self
def __exit__(self, exc_type, exc_val, exc_tb):
print('Exiting context')
with MyContextManager() as cm:
print('Inside the context')
# Output:
# Entering context
# Inside the context
# Exiting context
- Answer: Context managers are objects that enable proper resource management. They are used with the
-
Explain the purpose of
*args
and**kwargs
in Python function definitions.- Answer:
*args
: It allows you to pass a variable number of positional arguments to a function. It collects extra positional arguments into a tuple.**kwargs
: It allows you to pass a variable number of keyword arguments to a function. It collects extra keyword arguments into a dictionary.
def my_func(*args, **kwargs):
print(args) # Tuple of positional arguments
print(kwargs) # Dictionary of keyword arguments
my_func(1, 2, 3, a='apple', b='banana')
# Output:
# (1, 2, 3)
# {'a': 'apple', 'b': 'banana'}
- Answer:
-
What are Python decorators with arguments and how do you implement them?
- Answer: Decorators can take arguments by defining a function that returns a decorator function.
def repeat(num_times):
def decorator_repeat(func):
def wrapper(*args, **kwargs):
for _ in range(num_times):
result = func(*args, **kwargs)
return result
return wrapper
return decorator_repeat
@repeat(num_times=3)
def greet(name):
print(f'Hello, {name}')
greet('Alice')
# Output:
# Hello, Alice
# Hello, Alice
# Hello, Alice
- Answer: Decorators can take arguments by defining a function that returns a decorator function.
-
Explain the use of
collections
module in Python with examples.- Answer: The
collections
module provides alternatives to Python's built-in data structures like dictionaries, lists, sets, and tuples.from collections import defaultdict, namedtuple, Counter, deque
# defaultdict
colors = defaultdict(int)
colors['red'] += 1
print(colors['red']) # Output: 1
# namedtuple
Point = namedtuple('Point', ['x', 'y'])
p = Point(1, 2)
print(p.x, p.y) # Output: 1 2
# Counter
counts = Counter(['a', 'b', 'a', 'c'])
print(counts['a']) # Output: 2
# deque
d = deque([1, 2, 3])
d.appendleft(0)
print(d) # Output: deque([0, 1, 2, 3])
- Answer: The
-
How do you use the
__slots__
attribute in Python classes?- Answer:
__slots__
is used to explicitly declare instance attributes. It can save memory by preventing the creation of instance dictionaries for attributes.class MyClass:
__slots__ = ['x', 'y']
def __init__(self, x, y):
self.x = x
self.y = y
obj = MyClass(10, 20)
print(obj.x, obj.y) # Output: 10 20
- Answer:
-
Explain the purpose of the
@property
decorator in Python.- Answer:
@property
is used to define a method as a property of a class. It allows you to define a method that can be accessed like an attribute.class Circle:
def __init__(self, radius):
self.radius = radius
@property
def diameter(self):
return self.radius * 2
circle = Circle(5)
print(circle.diameter) # Output: 10
- Answer:
-
What are some best practices for writing Python code?
- Answer:
- Use meaningful variable and function names.
- Follow PEP 8 style guide for code readability.
- Write docstrings for all public modules, functions, classes, and methods.
- Use list comprehensions and generator expressions instead of loops where possible.
- Avoid using
global
variables unless absolutely necessary. - Write unit tests for your code using
unittest
orpytest
. - Use virtual environments (
venv
orconda
) for project isolation.
- Answer:
-
How do you profile Python code for performance optimization?
- Answer: You can use Python's built-in
cProfile
module or external tools likeline_profiler
andmemory_profiler
to profile code and identify bottlenecks.import cProfile
def my_function():
# Function code
cProfile.run('my_function()')
- Answer: You can use Python's built-in
-
Explain the GIL (Global Interpreter Lock) in Python and its impact on multi-threaded programs.
- Answer: The GIL is a mutex that protects access to Python objects, preventing multiple native threads from executing Python bytecodes simultaneously. It can impact multi-threaded programs by limiting CPU-bound concurrency but does not affect I/O-bound tasks or multiprocessing.
-
What are some differences between Python's
asyncio
andmultiprocessing
modules for concurrency?- Answer:
asyncio
: It is used for asynchronous programming with coroutines and event loops, suitable for I/O-bound tasks.multiprocessing
: It is used for parallelism by spawning multiple OS-level processes, suitable for CPU-bound tasks.
import asyncio
import multiprocessing
async def async_task():
# Asynchronous task
def sync_task():
# Synchronous task
# Example asyncio usage
asyncio.run(async_task())
# Example multiprocessing usage
p = multiprocessing.Process(target=sync_task)
p.start()
- Answer:
-
How do you manage Python dependencies in a project?
- Answer: Use a package manager like
pip
and create arequirements.txt
file listing all dependencies. Usevirtual environments
(venv
orconda
) to isolate project dependencies.
- Answer: Use a package manager like
-
Explain how Python's
unittest
andpytest
frameworks are used for testing.- Answer:
unittest
: It is Python's built-in unit testing framework, supporting test automation, sharing of setups, and shutdown code.pytest
: It is a third-party testing framework with features like fixtures, parameterization, and easy plugin integration.
import unittest
class MyTestCase(unittest.TestCase):
def test_addition(self):
self.assertEqual(1 + 1, 2)
if __name__ == '__main__':
unittest.main()
# Example using pytest
# test_my_module.py
import pytest
def test_addition():
assert 1 + 1 == 2
# Run with pytest command
- Answer:
-
Explain the use of
__new__()
and__init__()
methods in Python classes.- Answer:
__new__()
method: It is responsible for creating a new instance of a class. It is a static method and is called before__init__()
when an object is created.__init__()
method: It initializes the newly created object. It is called after the object has been created by__new__()
.
class MyClass:
def __new__(cls, *args, **kwargs):
print('Creating instance')
instance = super().__new__(cls)
return instance
def __init__(self, x):
print('Initializing instance')
self.x = x
obj = MyClass(10)
# Output:
# Creating instance
# Initializing instance
- Answer:
-
How do you handle circular imports in Python?
- Answer: Circular imports occur when two or more modules import each other directly or indirectly. You can resolve them by restructuring code or using
import
statements within functions.# Module A
from module_b import func_b
def func_a():
func_b()
# Module B
from module_a import func_a
def func_b():
func_a()
- Answer: Circular imports occur when two or more modules import each other directly or indirectly. You can resolve them by restructuring code or using
-
Explain the concept of metaclasses in Python with an example.
- Answer: Metaclasses are classes whose instances are classes themselves. They define the behavior of classes. Example using
type
as a metaclass:class MyMeta(type):
def __new__(cls, name, bases, dct):
dct['attr'] = 100
return super().__new__(cls, name, bases, dct)
class MyClass(metaclass=MyMeta):
pass
print(MyClass.attr) # Output: 100
- Answer: Metaclasses are classes whose instances are classes themselves. They define the behavior of classes. Example using
-
What are Python's magic methods (
__magic__
)? Provide examples of their usage.- Answer: Magic methods are special methods in Python that are surrounded by double underscores. They allow customization of classes to support various operations and behaviors.
class Vector:
def __init__(self, x, y):
self.x = x
self.y = y
def __add__(self, other):
return Vector(self.x + other.x, self.y + other.y)
def __str__(self):
return f'({self.x}, {self.y})'
v1 = Vector(1, 2)
v2 = Vector(3, 4)
print(v1 + v2) # Output: (4, 6)
- Answer: Magic methods are special methods in Python that are surrounded by double underscores. They allow customization of classes to support various operations and behaviors.
-
Explain the purpose of the
sys
module in Python.- Answer: The
sys
module provides access to system-specific parameters and functions. It can be used to interact with the interpreter and operating system.import sys
print(sys.version) # Output: Python version
print(sys.platform) # Output: Operating system platform
print(sys.argv) # Output: Command line arguments
- Answer: The
-
What is the purpose of Python's
itertools
module? Provide examples of its usage.- Answer: The
itertools
module provides functions that create iterators for efficient looping. Examples includecount()
,cycle()
,chain()
, andpermutations()
.import itertools
# Example of itertools.count()
for i in itertools.count(1, 2):
if i > 10:
break
print(i) # Output: 1, 3, 5, 7, 9
# Example of itertools.chain()
list1 = [1, 2, 3]
list2 = ['a', 'b', 'c']
combined = itertools.chain(list1, list2)
print(list(combined)) # Output: [1, 2, 3, 'a', 'b', 'c']
- Answer: The
-
How do you implement multiple inheritance in Python? What is the Method Resolution Order (MRO)?
- Answer: Multiple inheritance allows a class to inherit from multiple base classes. The MRO defines the order in which base classes are searched when looking for a method or attribute.
class A:
def process(self):
print('A process()')
class B(A):
def process(self):
print('B process()')
class C(A):
def process(self):
print('C process()')
class D(B, C):
pass
obj = D()
obj.process()
# Output: B process()
- Answer: Multiple inheritance allows a class to inherit from multiple base classes. The MRO defines the order in which base classes are searched when looking for a method or attribute.
-
Explain the concept of Python's
async
andawait
keywords for asynchronous programming.- Answer:
async
is used to define asynchronous functions (coroutines), andawait
is used to pause execution of an asynchronous function until a coroutine completes.import asyncio
async def async_task():
print('Task 1')
await asyncio.sleep(1)
print('Task 2')
asyncio.run(async_task())
# Output:
# Task 1
# (1 second delay)
# Task 2
- Answer:
-
What are
__slots__
and when would you use them in Python?- Answer:
__slots__
is used to explicitly declare instance attributes. It can save memory by preventing the creation of instance dictionaries for attributes.class MyClass:
__slots__ = ['x', 'y']
def __init__(self, x, y):
self.x = x
self.y = y
obj = MyClass(10, 20)
print(obj.x, obj.y) # Output: 10 20
- Answer:
-
Explain the purpose of the
functools
module in Python and provide examples of its usage.- Answer: The
functools
module provides higher-order functions for functional programming tasks. Examples includepartial()
,reduce()
, andlru_cache()
.from functools import lru_cache
@lru_cache(maxsize=32)
def fib(n):
if n < 2:
return n
return fib(n-1) + fib(n-2)
print(fib(10)) # Output: 55
- Answer: The
-
Explain the difference between
os.path.join()
andos.path.abspath()
in Python.- Answer:
os.path.join()
: It joins one or more path components intelligently using the correct separator for the operating system.os.path.abspath()
: It returns the absolute pathname of a given path, resolving any symbolic links if present.
import os
path = os.path.join('/Users', 'Alice', 'Documents', 'file.txt')
print(path) # Output: '/Users/Alice/Documents/file.txt'
abs_path = os.path.abspath('file.txt')
print(abs_path) # Output: '/Users/Alice/Documents/file.txt'
- Answer:
-
How do you handle JSON data in Python? Provide an example.
- Answer: Python's
json
module provides functions to encode Python objects as JSON strings and decode JSON strings into Python objects.import json
# Encoding Python object to JSON
data = {'name': 'Alice', 'age': 30}
json_str = json.dumps(data)
print(json_str) # Output: '{"name": "Alice", "age": 30}'
# Decoding JSON to Python object
decoded_data = json.loads(json_str)
print(decoded_data) # Output: {'name': 'Alice', 'age': 30}
- Answer: Python's
-
What are Python decorators used for, and how do you define a decorator with arguments?
- Answer: Decorators are used to modify the behavior of functions or methods. Decorators with arguments are defined using a nested function that returns a decorator function.
def repeat(num_times):
def decorator_repeat(func):
def wrapper(*args, **kwargs):
for _ in range(num_times):
result = func(*args, **kwargs)
return result
return wrapper
return decorator_repeat
@repeat(num_times=3)
def greet(name):
print(f'Hello, {name}')
greet('Alice')
# Output:
# Hello, Alice
# Hello, Alice
# Hello, Alice
- Answer: Decorators are used to modify the behavior of functions or methods. Decorators with arguments are defined using a nested function that returns a decorator function.
-
Explain the purpose of Python's
pickle
module.- Answer: The
pickle
module is used for serializing and deserializing Python objects. It can convert Python objects into a byte stream and vice versa.import pickle
# Serialize Python object to byte stream
data = {'name': 'Alice', 'age': 30}
serialized = pickle.dumps(data)
# Deserialize byte stream back to Python object
deserialized = pickle.loads(serialized)
print(deserialized) # Output: {'name': 'Alice', 'age': 30}
- Answer: The
-
What is a Python virtual environment (
venv
), and why would you use it?- Answer: A virtual environment (
venv
) is a self-contained directory that contains a Python installation for a specific version of Python, along with its own set of installed packages. It is used to isolate dependencies and project environments.# Creating a virtual environment
python -m venv myenv
# Activating the virtual environment (Windows)
myenv\Scripts\activate
# Activating the virtual environment (Unix/MacOS)
source myenv/bin/activate
- Answer: A virtual environment (
-
Explain the use of Python's
requests
module for making HTTP requests.- Answer: The
requests
module allows you to send HTTP requests easily and handle the responses.import requests
# Making a GET request
response = requests.get('https://jsonplaceholder.typicode.com/posts/1')
print(response.status_code) # Output: 200
print(response.json()) # Output: JSON response content
- Answer: The
-
How do you implement a simple Flask application in Python?
- Answer: Flask is a lightweight web framework for Python. Here's an example of a simple Flask application:
from flask import Flask
app = Flask(__name__)
@app.route('/')
def hello():
return 'Hello, World!'
if __name__ == '__main__':
app.run(debug=True)
- Answer: Flask is a lightweight web framework for Python. Here's an example of a simple Flask application:
-
What are context managers in Python, and how do you create one using the
contextlib
module?- Answer: Context managers in Python are objects that enable proper resource management using the
with
statement. You can create a context manager using thecontextlib
module'scontextmanager
decorator.from contextlib import contextmanager
@contextmanager
def file_manager(filename, mode):
try:
file = open(filename, mode)
yield file
finally:
file.close()
with file_manager('example.txt', 'w') as f:
f.write('Hello, World!')
- Answer: Context managers in Python are objects that enable proper resource management using the
-
How do you use Python's
argparse
module for command-line argument parsing?- Answer: The
argparse
module makes it easy to write user-friendly command-line interfaces. It parses arguments and options from the command line.import argparse
parser = argparse.ArgumentParser(description='Process some integers.')
parser.add_argument('integers', metavar='N', type=int, nargs='+',
help='an integer for the accumulator')
parser.add_argument('--sum', dest='accumulate', action='store_const',
const=sum, default=max,
help='sum the integers (default: find the max)')
args = parser.parse_args()
print(args.accumulate(args.integers))
- Answer: The
-
Explain the use of
@staticmethod
and@classmethod
decorators in Python.- Answer:
@staticmethod
: It defines a static method that does not operate on instances of a class and does not have access toself
orcls
.@classmethod
: It defines a class method that operates on the class itself rather than instances. It takescls
as the first parameter.
class MyClass:
class_attr = 10
@staticmethod
def static_method():
print('This is a static method')
@classmethod
def class_method(cls):
print(f'Class attribute: {cls.class_attr}')
MyClass.static_method() # Output: This is a static method
MyClass.class_method() # Output: Class attribute: 10
- Answer:
These questions cover various intermediate-level topics in Python that are frequently asked in interviews.